/*
 * @Author: jingfuu@163.com
 * @Date: 2024-11-29 17:06:33
 * @LastEditTime: 2024-12-11 14:22:57
 * @Description: file content
 */
import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Post,
  Put,
  Query,
  Sse,
  UnauthorizedException,
} from '@nestjs/common';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import NoticeService from '../service/NoticeService';
import NoticeQueryParam from '../param/NoticeQueryParam';
import NoticeDto from '../dto/NoticeDto';
import { R } from 'src/common/R';
import PageResult from 'src/common/PageResult';
import { ClsService } from 'nestjs-cls';
import { UserSession } from 'src/common/UserSession';
import { Constants } from 'src/common/Constants';
import { interval, Observable, switchMap } from 'rxjs';
import { CacheUtil } from 'src/common/CacheUtil';
import { CacheKey } from 'src/common/CacheKey';
import UserNoticeMsgUtil from 'src/common/UserNoticeMsgUtil';
import { PreAuthorize } from 'src/common/decorator/pre-authorize.decorator';
import { Log } from 'src/common/decorator/log';
import BusinessType from 'src/common/enum/BusinessType';

/*
 * @Author: jingfuu@163.com
 * @Date: 2024-11-29 17:06:33
 * @LastEditTime: 2024-11-29 17:18:07
 * @Description: 系统通知接口
 */
@ApiTags('系统通知')
@Controller('system/notice')
class NoticeController {
  constructor(
    private noticeService: NoticeService,
    private cls: ClsService,
  ) {}

  @PreAuthorize('system:notice:list')
  @ApiOperation({ summary: '分页查询' })
  @Get('/list')
  async findList(@Query() param: NoticeQueryParam): Promise<R<NoticeDto>> {
    const result: PageResult<NoticeDto> = await this.noticeService.list(param);
    return R.page(result);
  }

  @Log({ title: '系统通知', businessType: BusinessType.DELETE })
  @PreAuthorize('system:notice:remove')
  @ApiOperation({ summary: '删除' })
  @Delete('/:id')
  async delete(@Param('id') id: string): Promise<R<any>> {
    if (id.indexOf(',') > -1) {
      for (const item of id.split(',')) {
        await this.noticeService.deleteNotice(Number.parseInt(item));
      }
    } else {
      await this.noticeService.deleteNotice(Number.parseInt(id));
    }
    return R.ok();
  }

  @PreAuthorize('system:notice:query')
  @ApiOperation({ summary: '获取详情' })
  @Get('/:id(\\d+)')
  async findDetail(@Param('id') id: number): Promise<R<NoticeDto>> {
    const result = await this.noticeService.detail(id);
    return R.ok(result);
  }

  @Log({ title: '系统通知', businessType: BusinessType.UPDATE })
  @PreAuthorize('system:notice:edit')
  @ApiOperation({ summary: '修改' })
  @Put()
  async modifyPost(@Body() notice: NoticeDto): Promise<R<any>> {
    await this.noticeService.updateNotice(notice);
    return R.ok();
  }

  @Log({ title: '系统通知', businessType: BusinessType.INSERT })
  @PreAuthorize('system:notice:add')
  @ApiOperation({ summary: '新增' })
  @Post()
  async createPost(@Body() notice: NoticeDto): Promise<R<any>> {
    await this.noticeService.createNotice(notice);
    return R.ok();
  }

  @ApiOperation({ summary: '获取通知公告列表' })
  @Get('/all')
  async getNoticeList(): Promise<R<NoticeDto[]>> {
    const result = await this.noticeService.getAllNotice();
    return R.ok(result);
  }

  /**
   * 当前登录用户拉取私信通知
   */
  @ApiOperation({ summary: '获取指定用户通知' })
  @Get('/user')
  async getUserNotice(): Promise<R<NoticeDto>> {
    const userSession = this.cls.get<UserSession>(Constants.USER_SESSION);
    const result = await this.noticeService.getUserNotice(userSession.userId);
    return R.ok(result);
  }

  /**
   * 拉取消息数量，3s通知客户端一次
   * @returns 消息
   */
  @Get('/user/msg-count')
  @Sse()
  async userMsgCount(
    @Query('token') token: string,
  ): Promise<Observable<MessageEvent<any>>> {
    //验证token并获取用户信息
    const userId = await CacheUtil.getCacheObject<number>(
      CacheKey.USER_TOKEN + token,
    );
    if (!userId) {
      throw new UnauthorizedException();
    }
    return Promise.resolve(
      interval(3000).pipe(
        switchMap(async () => {
          const data = await this.noticeService.getUserNotice(userId);
          return new MessageEvent('message', { data });
        }),
      ),
    );
  }

  /**
   * 用户消息分页查询
   */
  @ApiOperation({ summary: '用户消息分页查询' })
  @Get('/user/list')
  async findUserNoticeList(
    @Query() param: NoticeQueryParam,
  ): Promise<R<NoticeDto>> {
    const userSession = this.cls.get<UserSession>(Constants.USER_SESSION);
    param.userId = userSession.userId;
    const result: PageResult<NoticeDto> =
      await this.noticeService.findUserNoticeList(param);
    return R.page(result);
  }

  /**
   * 用户消息全部标识为已读
   */
  @ApiOperation({ summary: '用户消息全部标识为已读' })
  @Put('/user/read-all')
  async readUserNoticeAll(): Promise<R<any>> {
    const userSession = this.cls.get<UserSession>(Constants.USER_SESSION);
    await this.noticeService.readUserNoticeAll(userSession.userId);
    return R.ok();
  }

  /**
   * 用户消息全部标识为已读
   */
  @ApiOperation({ summary: '用户读取单个消息' })
  @Put('/user/read/:noticeId(\\d+)')
  async readUserNoticeSingle(
    @Param('noticeId') noticeId: number,
  ): Promise<R<any>> {
    const userSession = this.cls.get<UserSession>(Constants.USER_SESSION);
    await this.noticeService.readUserNoticeSingle(userSession.userId, noticeId);
    return R.ok();
  }

  @ApiOperation({ summary: '系统通知消息发送测试' })
  @Post('/user/send')
  async sendUserNotice(@Body() notice: NoticeDto): Promise<R<any>> {
    UserNoticeMsgUtil.sendUserNoticeMsg(notice);
    return R.ok();
  }
}
export default NoticeController;
